local json = require "cjson"

--返回数据方法
local function responseMsg(code, msg, data)
    local rtn = {}
    rtn['code'] = code
    rtn['msg'] = msg
    rtn['data'] = data
    return json.encode(rtn)
end

local function inArray(needle, list)
    if list then
        for key, value in pairs(list) do
            if tonumber(value) == tonumber(needle) then
                return true
            end
        end
    end
    return false
end

local function getInventory(roundId, skuId)
    local inventoryCacheKey = string.format("zlj:jqq:activity:seckill:round:inventory:%s:%s", roundId, skuId)
    return red:llen(inventoryCacheKey)
end

local function submit(roundId, skuId, userId)
    local inventoryCacheKey = string.format("zlj:jqq:activity:seckill:round:inventory:%s:%s", roundId, skuId)
    local winnerCacheKey = string.format("zlj:jqq:activity:seckill:round:winner:%d:%d", roundId, skuId)
    local submitCacheKey = string.format("zlj:jqq:activity:seckill:round:submit:%d:%d:%d", roundId, skuId, userId)
    if red:exists(submitCacheKey) ~= 1 then
        local ticketNo = red:lpop(inventoryCacheKey)
        if ticketNo ~= ngx.null and ticketNo then
            local setWinnerResult = red:hset(winnerCacheKey, ticketNo, userId)
            local setSubmitResult = red:set(submitCacheKey, 1, 'ex', 5, 'nx');
            if setWinnerResult == 1 and setSubmitResult ~= ngx.null then
                return {ticket_no=ticketNo, round_id=roundId, sku_id=skuId}
            end
        end
    end
    return false
end

ngx.header["Access-Control-Allow-Origin"] = "*"
ngx.header["Access-Control-Allow-Headers"] = "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range, userid, agent, brandid, language, token"

--验证参数
local arg = ngx.req.get_uri_args()
local roundId = arg.round_id
if not roundId or #roundId <= 0 then
    ngx.say(responseMsg('2000', 'round_id参数有误', nil))
    return
end
local skuId = arg.sku_id
if not skuId or #skuId <= 0 then
    ngx.say(responseMsg('2000', 'sku_id参数有误', nil))
    return
end

-- 数据库、redis 等基础配置项
local env = ''
local mysql_prop = {}
local redis_prop = {}
local redis_prop_home = {}
if env == 'local' then
    mysql_prop = {
        host = "zljsz-testenvironmentdb.mysql.rds.aliyuncs.com",
        port = 3306,
        database = "panda_recovery",
        user = "code_test",
        password = "reVvtDiN2g3JaCxc"
    }

    redis_prop = {
        host = "zljsz-testenvironmentdb.redis.rds.aliyuncs.com",
        port = 6379,
        auth = 'lzWu9gskZ9OQrnOP'
    }
    redis_prop_home = {
        host = "zljsz-testenvironmentdb.redis.rds.aliyuncs.com",
        port = 6379,
        auth = 'lzWu9gskZ9OQrnOP'
    }
elseif env == 'test' then
    mysql_prop = {
        host = "zljsz-testenvironmentdb.mysql.rds.aliyuncs.com",
        port = 3306,
        database = "panda_recovery",
        user = "code_test",
        password = "reVvtDiN2g3JaCxc"
    }

    redis_prop = {
        host = "zljsz-testenvironmentdbvpc.redis.rds.aliyuncs.com",
        port = 6379,
        auth = 'lzWu9gskZ9OQrnOP'
    }
    redis_prop_home = {
        host = "zljsz-testenvironmentdbvpc.redis.rds.aliyuncs.com",
        port = 6379,
        auth = 'lzWu9gskZ9OQrnOP'
    }
else
    mysql_prop = {
        host = "rm-wz9s54k9r047b5012rw.mysql.rds.aliyuncs.com",
        port = 3306,
        database = "panda_recovery",
        user = "code_recovery",
        password = "xGvyhcnXL49RWz1N"
    }

    redis_prop = {
        host = "zljsz-recoverydbvpc.redis.rds.aliyuncs.com",
        port = 6379,
        auth = 'NeSt6Wauy3ZKqEMR'
    }
    redis_prop_home = {
        host = "zljsz-redis1dbvpc.redis.rds.aliyuncs.com",
        port = 6379,
        auth = 'JtS42CKZsepk88EX'
    }
end

--连接redis
local redis = require "resty.redis"
zljRed = redis:new()
local ok, err = zljRed:connect(zljRedisConfig['host'], zljRedisConfig['port'])   --连接redis
if not ok then
    ngx.say(responseMsg('-1', json.encode(err), nil))
    return
end
--连接redis密码
ok, err = zljRed:auth(zljRedisConfig['auth'])   --连接redis
if not ok then    -- 链接失败的时候
    ngx.say(responseMsg('1002', json.encode(err), nil));
    return
end

local token = arg.token
if not token then
    ngx.say(responseMsg('-401', "用户token为空", nil));
    return
end
local userId = 0;
if token and #token > 0 then
    userId = zljRed:get(token);
end

if userId == ngx.null or userId == 0 then
    ngx.say(responseMsg('-401', "用户token无效，请重新登录", nil));
    return
end

red = redis:new()
local ok, err = red:connect(recoveryRedisConfig['host'], recoveryRedisConfig['port'])   --连接redis
if not ok then
    ngx.say(responseMsg('1002', json.encode(err), nil))
    return
end
--连接redis密码
ok, err = red:auth(recoveryRedisConfig['auth'])   --连接redis
if not ok then    -- 链接失败的时候
    ngx.say(responseMsg('1002', json.encode(err), nil));
    return
end

red:select(1)

local roundCacheKey = "zlj:jqq:activity:seckill:round:entity:"..roundId
local cacheData = red:get(roundCacheKey)
if tostring(type(cacheData)) ~= 'string' then
    ngx.say(responseMsg("2001", "round不存在", nil))
    return
end

local roundData = json.decode(cacheData)
if os.time() < roundData['start_timestamp'] then
    ngx.say(responseMsg("2002", "秒杀活动还未开始", nil))
    return
end

if os.time() > roundData['end_timestamp'] then
    ngx.say(responseMsg("2003", "秒杀活动已结束", nil))
    return
end

if not inArray(skuId, roundData['sku_ids']) then
    ngx.say(responseMsg("2004", "该活动不包含此商品", inArray(skuId, roundData['sku_ids'])))
    return
end

local inventory = getInventory(roundId, skuId)
if inventory == 0 then
    ngx.say(responseMsg("2005", "已经抢完了，请下次再来"))
    return
end

local realStartTimestamp = math.random(1,3) + roundData['start_timestamp']
if os.time() > realStartTimestamp then
    data = submit(roundId, skuId, userId)
    if data then
        ngx.say(responseMsg('1', "", data))
        return
    end
end

ngx.say(responseMsg('-1', "抱歉，您没抢到", nil))
return